//
//  SKUICellLabel.m
//  Sudoku
//
//  Created by Richard Hodgkins on 09/09/2012.
//  Copyright (c) 2012 Richard Hodgkins. All rights reserved.
//

#import "SKUICellLabel.h"

#define EMPTY_CELL 0
#define FIXED_CELL -1

#define TEXT_COLOR_FIXED UIColorFromRGB(0x000000)
#define TEXT_COLOR_EDITABLE UIColorFromRGB(0x0000FF)
#define TEXT_COLOR_EDITABLE_CUSTOM UIColorFromRGB(0x00AA00)
#define TEXT_COLOR_PENCIL UIColorFromRGB(0xFF0000)

@interface SKUICellLabel ()

@property (nonatomic, assign) SInt8 originalNumber, currentNumber, pencilNumber;
@property (nonatomic, assign) id<SKCellDelegate> delegate;
@property (nonatomic, assign) BOOL isInPencilMode;

@end

@implementation SKUICellLabel

- (id)initWithFrame:(CGRect)frame andNumber:(SInt8)number andDelegate:(id<SKCellDelegate>)delegate
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.originalNumber = number;
        self.delegate = delegate;

        self.backgroundColor = [UIColor clearColor];
        self.adjustsFontSizeToFitWidth = YES;
        self.textAlignment = NSTextAlignmentCenter;
        self.userInteractionEnabled = YES;
        
        self.font = [self.font fontWithSize:IS_IPAD() ? 54 : 22];
        
        if ([self isEditable]) {
            // Only set a tap listener if we're editable
            UIGestureRecognizer *tapGestureRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)];
            [self addGestureRecognizer:tapGestureRecog];
            
            // Only set a long press listener if we're editable
            UIGestureRecognizer *longPressGestureRecog = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLongPress:)];
            [self addGestureRecognizer:longPressGestureRecog];
            
        } else {
            // Non editable cells have their own color
            self.textColor = TEXT_COLOR_FIXED;
        }
        
        [self reset];
    }
    return self;
}

// previous move is 8 bits, least sig. 4 bits are current move, most sig. 4 bits are pencil move
- (id)initWithFrame:(CGRect)frame andNumber:(SInt8)number andPreviousMove:(SInt8)previousMove andDelegate:(id<SKCellDelegate>)delegate
{
    self = [self initWithFrame:frame andNumber:number andDelegate:delegate];
    if (self) {
        const SInt8 previousNumber = (0x0F & previousMove);
        const SInt8 previousPencil = (0xF0 & previousMove) >> 4;

        [self updateNumber:previousNumber andPencilNumber:previousPencil];
    }
    return self;
}

- (SInt8) currentMove
{
    if ([self isEditable]) {
        return (self.pencilNumber << 4) | self.currentNumber;
    } else {
        return FIXED_CELL;
    }
}

- (BOOL) isEditable
{
    return self.originalNumber < 0;
}

- (BOOL) updateCurrentNumber:(SInt8) number
{
    return [self updateNumber:number andPencilNumber:EMPTY_CELL];
}

- (BOOL) updatePencilNumber:(SInt8) number
{
    return [self updateNumber:self.currentNumber andPencilNumber:number];
}

- (BOOL) updateNumber:(SInt8) currentNumber andPencilNumber:(SInt8) pencilNumber
{
    if ([self isEditable]) {
        
        UIColor *textColor = [SKUICellLabel editableTextColor];
        SInt8 number, oldNumber;
        if (self.isInPencilMode) {
            oldNumber = self.pencilNumber;
            number = pencilNumber;
            if (self.currentNumber == EMPTY_CELL) {
                textColor = TEXT_COLOR_PENCIL;
            }
        } else {
            oldNumber = self.currentNumber;
            number = currentNumber;
            textColor = [SKUICellLabel editableTextColor];
        }
        // Set the color relative to the mode
        self.textColor = textColor;
        // Set the value, or clear the text if it was empty
        self.text = number == EMPTY_CELL ? nil : [@(number) stringValue];
        
        self.currentNumber = currentNumber;
        self.pencilNumber = pencilNumber;
        
        // Check if we changed the value
        return number != oldNumber;
    } else {
        self.text = [@(self.originalNumber) stringValue];
        // We didn't change the value
        return NO;
    }
}

- (void) updatePencilMode:(BOOL)isInPencilMode
{
    if (self.isInPencilMode != isInPencilMode) {
        // Only bother doing anything if we've changed the value
        self.isInPencilMode = isInPencilMode;
        if ([self isEditable]) {
            if (self.currentNumber == EMPTY_CELL) {
                if (self.isInPencilMode) {
                    // We're in pencil mode set the pencil number to a previous value, or the current number if one has not been set
                    [self updatePencilNumber:self.pencilNumber == EMPTY_CELL ? self.currentNumber : self.pencilNumber];
                } else {
                    // We're not in pencil mode anymore so save the old number
                    [self updateNumber:self.currentNumber andPencilNumber:self.pencilNumber];
                }
            }
        }
    }
}

- (BOOL) reset
{
    if (self.isInPencilMode) {
        // If we're in pencil mode just clear the value
        // We're in pencil mode set the pencil number to a previous value, or the current number if one has not been set
        return [self updatePencilNumber:self.currentNumber];
    } else {
        // Else clear everything
        return [self updateNumber:EMPTY_CELL andPencilNumber:EMPTY_CELL];
    }
}

- (SKCellState) state
{
    if ([self isEditable]) {
        if (self.currentNumber == EMPTY_CELL) {
            return SKCellStateEmpty;
        } else {
            // The number is only correct if it matches the original number
            if (self.currentNumber == -self.originalNumber) {
                return SKCellStateCorrect;
            } else {
                return SKCellStateIncorrect;
            }
        }
    } else {
        // We're not an editable cell so it's already correct
        return SKCellStateCorrect;
    }
}

#pragma mark - Gesture selectors

- (void) didTap:(UIGestureRecognizer *) gesture
{
    [self.delegate didTapCell:gesture.view];
}

- (void) didLongPress:(UIGestureRecognizer *) gesture
{
    BOOL inNeedOfUpdate;
    if (self.isInPencilMode) {
        inNeedOfUpdate = [self updatePencilNumber:EMPTY_CELL];
    } else {
        inNeedOfUpdate = [self updateNumber:EMPTY_CELL andPencilNumber:self.pencilNumber];
    }
    if (inNeedOfUpdate) {
        [self.delegate didResetCell:gesture.view];
    }
}

#pragma mark - Text color

// Convience method to get the edit cell color depending on the device
+ (UIColor *) editableTextColor
{
    return [SKUtils isCustomDevice] ? TEXT_COLOR_EDITABLE_CUSTOM : TEXT_COLOR_EDITABLE;
}

@end
